package mock

import (
	"bytes"
	"encoding/json"
	"fmt"
	"gitee.com/bigmouth/quick-mock/src/domain/service"
	"gitee.com/bigmouth/quick-mock/src/infrastructure/server"
	"github.com/gin-gonic/gin"
	"net/http"
	"time"
)

/**
* @Author: huangyi
* @Date: 2022/7/7 07:06
 */

type ResponseTemplateEnv struct {
	Header map[string]string
	Body   map[string]interface{}
	Param  map[string]string
}

func mockByNamespace(c *gin.Context, namespace string) {
	startTime := time.Now()
	templateEnv := ResponseTemplateEnv{}
	// path
	path := c.Param("mockPath")
	// method
	method := c.Request.Method
	// query param
	queryParams := make(map[string]string)
	if len(c.Request.URL.Query()) > 0 {
		for k, v := range c.Request.URL.Query() {
			if len(v) > 0 {
				queryParams[k] = v[0]
			}

		}
	}
	templateEnv.Param = queryParams
	// header
	header := make(map[string]string)
	if len(c.Request.Header) > 0 {
		for k, v := range c.Request.Header {
			if len(v) > 0 {
				header[k] = v[0]
			}

		}
	}
	templateEnv.Header = header
	// body
	bodyJson := make(map[string]interface{})
	if err := c.Bind(&bodyJson); err != nil {
		c.AbortWithStatusJSON(http.StatusInternalServerError, server.Fail(err.Error()))
		return
	}
	templateEnv.Body = bodyJson
	mockApi, ok, err := service.GetNamespaceInstance().MatchMock(namespace, path, method, header, queryParams, bodyJson)
	if err != nil {
		c.AbortWithStatusJSON(http.StatusInternalServerError, server.Fail(err.Error()))
		return
	}
	if !ok {
		c.AbortWithStatusJSON(http.StatusNotFound, server.Fail("接口不存在"))
		return
	}
	endTime := time.Now()
	respCost := endTime.Sub(startTime).Milliseconds()
	// responseJsonData支持go template
	responseData := make([]byte, 0, len([]byte(mockApi.ResponseJsonDataStr)))
	buff := bytes.NewBuffer(responseData)
	if mockApi.ResponseJsonDataTemplate != nil {
		if err := mockApi.ResponseJsonDataTemplate.Execute(buff, templateEnv); err != nil {
			c.AbortWithStatusJSON(http.StatusNotFound, server.Fail("解析responseBodyJson错误，请检查是否符合go template的语法"))
			return
		}
	}
	responseDataJson := make(map[string]interface{})
	if err := json.Unmarshal(buff.Bytes(), &responseDataJson); err != nil {
		c.AbortWithStatusJSON(http.StatusInternalServerError, server.Fail("反序列化成json失败， err=%s", buff.String()))
		return
	}
	// 处理延迟
	if mockApi.Delay > 0 && respCost < mockApi.Delay {
		fmt.Printf("delay: %d", mockApi.Delay-respCost)
		time.Sleep(time.Duration(mockApi.Delay-respCost) * time.Millisecond)
	}
	c.JSON(http.StatusOK, responseDataJson)
}
